home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / OpenDoc 1.2b2c1 / Implementation / Memory / MemoryHe.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-13  |  27.3 KB  |  971 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        MemoryHe.cpp
  3.  
  4.     Contains:    MemoryHeap class implementation
  5.  
  6.     Owned by:    Michael Burbidge, Jens Alfke
  7.     Owned by:    Jens Alfke
  8.  
  9.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  10.  
  11.     Change History (most recent first):
  12.     
  13.          <3>    27.09.1996    NP        1386083: Changes to Allocate
  14.          <2>     9/13/96    jpa        1371387: Speed optimizations.
  15.         <16>    10/24/95    jpa        1293441: Added slush-fund.
  16.         <15>      8/4/95    DM        Leak detection [1267956]
  17.         <14>      6/7/95    jpa        IsValidBlock calls hooks to check for
  18.                                     prefix/suffix validity. [1256829]
  19.         <13>      5/5/95    TJ        jpa: Don't call hooks in nondebug build.
  20.         <12>      5/4/95    jpa        Support for finding largest free block
  21.                                     [1235657] and validating memory ranges
  22.                                     [1246077]
  23.         <11>    12/20/94    jpa        Fixed constructor typo that turned on
  24.                                     fZapOnFree.
  25.         <10>     12/5/94    jpa        Nuked errant pragma lib_export's. [1195676]
  26.          <9>    10/24/94    jpa        Constness [1194286].
  27.          <8>     9/29/94    RA        1189812: Mods for 68K build.
  28.          <7>     9/14/94    jpa        Eliminated dependencies on rest of OpenDoc.
  29.                                     Added support for getting the heap of a
  30.                                     block. [1186692]
  31.          <6>     8/17/94    jpa        Added support for walking heaps [1179567].
  32.          <5>      8/8/94    jpa        Zap old block after reallocate.
  33.          <4>      8/2/94    jpa        Fixed bug in BlockSize (wasn't calling
  34.                                     hooks when it should)
  35.          <3>     6/18/94    MB        More initial SOM deployment
  36.          <2>     6/10/94    MB        Make it build
  37.          <1>      6/9/94    MB        first checked in
  38.          <3>     5/26/94    MB        #1162181: Fixed MMM integration bug
  39.          <2>      5/9/94    MB        #1162181: Changes necessary to install MMM.
  40.          <1>     4/29/94    MB        first checked in
  41.     To Do:
  42.     In Progress:
  43.         
  44. */
  45.  
  46. #ifndef _PLATFMEM_
  47. #include "PlatfMem.h"
  48. #endif
  49.  
  50. #ifndef _MEMORYHE_
  51. #include "MemoryHe.h"
  52. #endif
  53.  
  54. #ifndef _MEMHOOKS_
  55. #include "MemHooks.h"
  56. #endif
  57.  
  58. #ifndef __MEMORY__
  59. #include <Memory.h>
  60. #endif
  61.  
  62. #ifndef __STDIO__
  63. #include <stdio.h>
  64. #endif
  65.  
  66.  
  67. #if MM_INSTRUMENT
  68. const long kNAllocCounters = 100;
  69. unsigned long gAllocCounter[kNAllocCounters+1];
  70. #endif
  71.  
  72.  
  73. //========================================================================================
  74. // CLASS MemoryHeap
  75. //========================================================================================
  76.  
  77. const char *MemoryHeap::kDefaultDescription = "Give this MemoryHeap a description";
  78. const char *MemoryHeap::kDeadHeapDescription = "Dead heap, dead heap, dead heap!";
  79. MemoryHeap *MemoryHeap::fHeapList;                                // Don't initialize!
  80.  
  81. //----------------------------------------------------------------------------------------
  82. // MemoryHeap::ValidateMagicNumber  (MM_DEBUG only)
  83. //----------------------------------------------------------------------------------------
  84.  
  85. #if MM_DEBUG
  86.  
  87.     #pragma segment HeapSeg
  88.     mmboolean MemoryHeap::ValidateMagicNumber( ) const
  89.     {
  90.         if( fMagicNumber != kMagicNumber ) {
  91.             MM_WARN("Invalid magic number for heap %d -- is this a valid heap?",this);
  92.             return kMMFalse;
  93.         } else
  94.             return kMMTrue;
  95.     }
  96.     
  97. #endif
  98.  
  99. //----------------------------------------------------------------------------------------
  100. // MemoryHeap::GetFirstHeap
  101. //----------------------------------------------------------------------------------------
  102. #pragma segment HeapSeg
  103.  
  104. MemoryHeap *MemoryHeap::GetFirstHeap()
  105. {
  106.     return fHeapList;
  107. }
  108.  
  109. //----------------------------------------------------------------------------------------
  110. // MemoryHeap::Allocate
  111. //----------------------------------------------------------------------------------------
  112. #pragma segment HeapSeg
  113.  
  114. void *MemoryHeap::Allocate(ODBlockSize size)
  115. {
  116.     this->ValidateMagicNumber();
  117.  
  118. #if MM_INSTRUMENT
  119.     ODBlockSize index = (size+3) >>2;
  120.     if( index < kNAllocCounters )
  121.         gAllocCounter[index]++;
  122.     else
  123.         gAllocCounter[kNAllocCounters]++;
  124. #endif
  125.  
  126.     ODBlockSize originalSize = size;
  127. #if MM_DEBUG
  128.     size = this->CallAboutToAllocateHooks(size);
  129. #endif
  130.  
  131.     ODBlockSize    allocatedSize;
  132.     void*        blk;
  133. #if MM_DEBUG
  134.     size_t    bytesFree;
  135.     bytesFree = this->BytesFree();
  136.     if (bytesFree - size < fMemFullMark)
  137.         blk = kMMNULL;
  138.     else
  139. #endif
  140.     blk = this->DoAllocate( size, allocatedSize);
  141.     
  142.     if (blk != kMMNULL) {
  143.         #if MM_DEBUG
  144.         if (fZapOnAllocate)
  145.             PlatformZapMem(blk,allocatedSize,0xBBBBBBBB);
  146.         #endif
  147.         fBytesAllocated += allocatedSize;
  148.         fNumberAllocatedBlocks++;
  149.         
  150.     } else if( originalSize<=fSlushFundAllocSizeLimit ) {
  151.         // Free slush fund. Do not try again, let the caller know it ran out of memory.
  152.         // But a little memory will now be available to make cleanup possible.
  153.         MM_WARN( this->GetSlushFundSize()>0 ?"Out of memory. Freed slush fund."
  154.                                             :"Out of memory, no slush fund. Oh, dear." );
  155.         this->FreeSlushFund();
  156.     }
  157.     
  158. #if MM_DEBUG
  159.     blk = this->CallDidAllocateHooks(blk, size);
  160. #endif
  161.  
  162.     return blk;
  163. }
  164.  
  165. //----------------------------------------------------------------------------------------
  166. // MemoryHeap::BlockSize
  167. //----------------------------------------------------------------------------------------
  168. #pragma segment HeapSeg
  169.  
  170. ODBlockSize MemoryHeap::BlockSize(const void *blk) const
  171. {
  172.     this->ValidateMagicNumber();
  173.  
  174.     if (blk == NULL)
  175.         return 0;
  176.         
  177. #if MM_DEBUG
  178.     if (fAutoValidation)
  179.         this->ValidateAndReport((void*)blk);
  180.         
  181.     blk = ((MemoryHeap *) this)->CallAboutToBlockSizeHooks((void*)blk);
  182. #endif
  183.  
  184.     ODBlockSize size = this->DoBlockSize((void*)blk);
  185.  
  186. #if MM_DEBUG
  187.     size -= this->CallAboutToAllocateHooks(0);        // Subtract hook pad size
  188. #endif
  189.     return size;
  190. }
  191.  
  192. //----------------------------------------------------------------------------------------
  193. // MemoryHeap::BytesAllocated
  194. //----------------------------------------------------------------------------------------
  195. #pragma segment HeapSeg
  196.  
  197. unsigned long MemoryHeap::BytesAllocated() const
  198. {
  199.     this->ValidateMagicNumber();
  200.  
  201.     return fBytesAllocated;
  202. }
  203.  
  204. //----------------------------------------------------------------------------------------
  205. // MemoryHeap::Free
  206. //----------------------------------------------------------------------------------------
  207. #pragma segment HeapSeg
  208.  
  209. void MemoryHeap::Free(void* blk)
  210. {
  211.     this->ValidateMagicNumber();
  212.  
  213.     if (blk == NULL)
  214.         return;
  215.         
  216. #if MM_DEBUG
  217.     if (fAutoValidation)
  218.         this->ValidateAndReport(blk);
  219.         
  220.     blk = this->CallAboutToFreeHooks(blk);
  221. #endif
  222.     
  223.     ODBlockSize allocatedSize = (ODBlockSize) this->DoBlockSize(blk);
  224.     
  225.     #if MM_DEBUG
  226.     if (fZapOnFree)
  227.             PlatformZapMem(blk,allocatedSize,0xDDDDDDDD);
  228.     #endif
  229.  
  230.     this->DoFree(blk);
  231.  
  232.     fBytesAllocated -= allocatedSize;
  233.     fNumberAllocatedBlocks--;
  234. }
  235.  
  236. //----------------------------------------------------------------------------------------
  237. // MemoryHeap::LargestFreeBlock
  238. //----------------------------------------------------------------------------------------
  239. #pragma segment HeapSeg
  240.  
  241. unsigned long MemoryHeap::LargestFreeBlock( ) const
  242. {
  243.     long result = this->DoLargestFreeBlock();
  244. #if MM_DEBUG
  245.     result -= this->CallAboutToAllocateHooks(0);
  246. #endif
  247.     return result>0 ?result :0;
  248. }
  249.  
  250. #if MM_DEBUG
  251. //----------------------------------------------------------------------------------------
  252. // MemoryHeap::GetAutoValidation (MM_DEBUG only)
  253. //----------------------------------------------------------------------------------------
  254. #pragma segment HeapSeg
  255.  
  256. mmboolean MemoryHeap::GetAutoValidation() const
  257. {
  258.     this->ValidateMagicNumber();
  259.  
  260.     return fAutoValidation;
  261. }
  262. #endif
  263.  
  264. //----------------------------------------------------------------------------------------
  265. // MemoryHeap::GetDescription
  266. //----------------------------------------------------------------------------------------
  267. #pragma segment HeapSeg
  268.  
  269. const char *MemoryHeap::GetDescription() const
  270. {
  271.     this->ValidateMagicNumber();
  272.  
  273.     return fDescription;
  274. }
  275.  
  276. //----------------------------------------------------------------------------------------
  277. // MemoryHeap::GetNextHeap
  278. //----------------------------------------------------------------------------------------
  279. #pragma segment HeapSeg
  280.  
  281. MemoryHeap *MemoryHeap::GetNextHeap() const
  282. {
  283.     return fNextHeap;
  284. }
  285.  
  286. //----------------------------------------------------------------------------------------
  287. // MemoryHeap::GetZapOnAllocate
  288. //----------------------------------------------------------------------------------------
  289. #pragma segment HeapSeg
  290.  
  291. #if MM_DEBUG
  292. mmboolean MemoryHeap::GetZapOnAllocate() const
  293. {
  294.     this->ValidateMagicNumber();
  295.  
  296.     return fZapOnAllocate;
  297. }
  298. #endif
  299.  
  300. //----------------------------------------------------------------------------------------
  301. // MemoryHeap::GetZapOnFree
  302. //----------------------------------------------------------------------------------------
  303. #pragma segment HeapSeg
  304.  
  305. #if MM_DEBUG
  306. mmboolean MemoryHeap::GetZapOnFree() const
  307. {
  308.     this->ValidateMagicNumber();
  309.  
  310.     return fZapOnFree;
  311. }
  312. #endif
  313.  
  314. #if MM_DEBUG
  315. //----------------------------------------------------------------------------------------
  316. // MemoryHeap::AdoptHook (MM_DEBUG only)
  317. //----------------------------------------------------------------------------------------
  318. #pragma segment HeapSeg
  319.  
  320. void MemoryHeap::AdoptHook(ODMemoryHook *memoryHook)
  321. {
  322.     this->ValidateMagicNumber();
  323.  
  324.     fMemoryHookList.Add(memoryHook);
  325. }
  326. #endif
  327.  
  328. #if MM_DEBUG
  329. //----------------------------------------------------------------------------------------
  330. // MemoryHeap::IsValidBlock (MM_DEBUG only)
  331. //----------------------------------------------------------------------------------------
  332. #pragma segment HeapSeg
  333.  
  334. mmboolean MemoryHeap::IsValidBlock(const void *blk) const
  335. {
  336.     this->ValidateMagicNumber();
  337.  
  338.     if (blk == NULL)
  339.         return false;
  340.     
  341.     blk = this->CallAboutToBlockSizeHooks(blk);
  342.         
  343.     if (this->IsMyBlock(blk))
  344.         return DoIsValidBlock(blk);
  345.     else
  346.         return false;
  347. }
  348. #endif
  349.  
  350. #if MM_DEBUG
  351. //----------------------------------------------------------------------------------------
  352. // MemoryHeap::FindBlockContaining (MM_DEBUG only)
  353. //----------------------------------------------------------------------------------------
  354. #pragma segment HeapSeg
  355.  
  356. mmboolean MemoryHeap::FindBlockContaining( const void *start, const void *end,
  357.                                             const void* &blockStart, const void* &blockEnd ) const
  358. {
  359.     this->ValidateMagicNumber();
  360.  
  361.     if( ! this->DoFindBlockContaining(start,end, blockStart,blockEnd) )
  362.         return kMMFalse;
  363.     else {
  364.         if( blockStart ) {
  365.             ODBlockSize hdrSize = this->CallGetHeaderSize();
  366.             blockStart = (char*)blockStart + hdrSize;
  367.             blockEnd   = (char*)blockEnd - (this->CallAboutToAllocateHooks(0) - hdrSize);
  368.         }
  369.         return kMMTrue;
  370.     }
  371. }
  372. #endif
  373.  
  374. //----------------------------------------------------------------------------------------
  375. // MemoryHeap::NumberAllocatedBlocks
  376. //----------------------------------------------------------------------------------------
  377. #pragma segment HeapSeg
  378.  
  379. unsigned long MemoryHeap::NumberAllocatedBlocks() const
  380. {
  381.     this->ValidateMagicNumber();
  382.  
  383.     return fNumberAllocatedBlocks;
  384. }
  385.  
  386. //----------------------------------------------------------------------------------------
  387. // MemoryHeap::SetBlockIsObject
  388. //----------------------------------------------------------------------------------------
  389. void MemoryHeap::SetBlockIsObject( void* ptr, mmboolean isObject )
  390. {
  391.     this->ValidateMagicNumber();
  392. #if MM_DEBUG
  393.     ptr = (void*) CallAboutToBlockSizeHooks(ptr);
  394. #endif
  395.     this->DoSetBlockIsObject(ptr,isObject );
  396. }
  397.  
  398. //----------------------------------------------------------------------------------------
  399. // MemoryHeap::BlockIsObject
  400. //----------------------------------------------------------------------------------------
  401. mmboolean MemoryHeap::BlockIsObject( const void* ptr ) const
  402. {
  403.     this->ValidateMagicNumber();
  404. #if MM_DEBUG
  405.     ptr = CallAboutToBlockSizeHooks(ptr);
  406. #endif
  407.     return this->DoBlockIsObject(ptr);
  408. }
  409.  
  410. #if MM_DEBUG
  411. //----------------------------------------------------------------------------------------
  412. // MemoryHeap::SetBlockStackCrawl
  413. //----------------------------------------------------------------------------------------
  414. void MemoryHeap::SetBlockStackCrawl( const void* blk, StackCrawl *s )
  415. {
  416.     this->ValidateMagicNumber();
  417.     for (ODMemoryHook *hook = fMemoryHookList.Last();
  418.             hook != NULL; hook = fMemoryHookList.Before(hook)) {
  419.         blk = hook->AboutToBlockSize(blk);
  420.         if( hook->GetType() == CBlockStackCrawlHook::kHookType ) {
  421.             ((CBlockStackCrawlHook*)hook)->SetStackCrawl(blk,s);
  422.             return;
  423.         }
  424.     }
  425.     MM_WARN("No BlockStackCrawlHook for SetBlockStackCrawl");
  426. }
  427.  
  428. //----------------------------------------------------------------------------------------
  429. // MemoryHeap::GetBlockStackCrawl
  430. //----------------------------------------------------------------------------------------
  431. StackCrawl* MemoryHeap::GetBlockStackCrawl( const void* blk ) const
  432. {
  433.     this->ValidateMagicNumber();
  434.     for (ODMemoryHook *hook = fMemoryHookList.Last();
  435.             hook != NULL; hook = fMemoryHookList.Before(hook)) {
  436.         blk = hook->AboutToBlockSize(blk);
  437.         if( hook->GetType() == CBlockStackCrawlHook::kHookType ) {
  438.             return ((CBlockStackCrawlHook*)hook)->GetStackCrawl(blk);
  439.         }
  440.     }
  441.     MM_WARN("No BlockStackCrawlHook for GetBlockStackCrawl");
  442.     return NULL;
  443. }
  444.  
  445. //----------------------------------------------------------------------------------------
  446. // MemoryHeap::GetBlockRealSize
  447. //----------------------------------------------------------------------------------------
  448. ODBlockSize MemoryHeap::GetBlockRealSize( const void* blk ) const
  449. {
  450.     this->ValidateMagicNumber();
  451.     for (ODMemoryHook *hook = fMemoryHookList.Last();
  452.             hook != NULL; hook = fMemoryHookList.Before(hook)) {
  453.         blk = hook->AboutToBlockSize(blk);
  454.         if( hook->GetType() == CBlockCushionHook::kHookType ) {
  455.             return ((CBlockCushionHook*)hook)->GetBlockSize(blk);
  456.         }
  457.     }
  458.     MM_WARN("No BlockCushionHook for GetBlockRealSize");
  459.     return NULL;
  460. }
  461. #endif
  462.  
  463. //----------------------------------------------------------------------------------------
  464. // MemoryHeap::Reallocate
  465. //----------------------------------------------------------------------------------------
  466. #pragma segment HeapSeg
  467.  
  468. void *MemoryHeap::Reallocate(void *blk, ODBlockSize newSize)
  469. {
  470.     this->ValidateMagicNumber();
  471.  
  472.     if (blk == NULL)
  473.         return this->Allocate(newSize);
  474.         
  475.     ODBlockSize allocatedSize;
  476.     ODBlockSize oldBlkSize = (ODBlockSize) this->BlockSize(blk);
  477.     
  478. #if MM_DEBUG
  479.     void *oldBlk = blk;
  480.     this->CallAboutToReallocHooks(blk, newSize);
  481. #endif
  482.     
  483.     blk = this->DoReallocate(blk, newSize, allocatedSize);
  484.     
  485.     if (blk != NULL)
  486.         fBytesAllocated += allocatedSize - oldBlkSize;
  487.             
  488. #if MM_DEBUG
  489.     blk = this->CallDidReallocHooks(oldBlk,blk, newSize);
  490. #endif
  491.  
  492.     return blk;
  493. }
  494.  
  495.  
  496. //----------------------------------------------------------------------------------------
  497. // MemoryHeap::AllocateSlushFund
  498. //----------------------------------------------------------------------------------------
  499. #pragma segment HeapSeg
  500. mmboolean MemoryHeap::AllocateSlushFund( size_t size, size_t allocSizeLimit )
  501. {
  502.     if( size==0 ) {
  503.         this->FreeSlushFund();
  504.         return kMMTrue;
  505.     }
  506.     this->Free(fSlushFund);
  507.     size_t oldLimit = fSlushFundAllocSizeLimit;
  508.     fSlushFundAllocSizeLimit = 0;
  509.     MMBlock slushy = this->Allocate(size);
  510.     if( !slushy ) {
  511.         if( fSlushFund ) {
  512.             fSlushFund = this->Allocate(fSlushFundSize);
  513.             if( !fSlushFund ) 
  514.                 MM_WARN("Yow! Lost slush fund accidentally");
  515.         }
  516.         return kMMFalse;
  517.     }
  518.     fSlushFund = slushy;
  519.     fSlushFundSize = size;
  520.     fSlushFundAllocSizeLimit = allocSizeLimit;
  521.     return kMMTrue;
  522. }
  523.  
  524. //----------------------------------------------------------------------------------------
  525. // MemoryHeap::FreeSlushFund
  526. //----------------------------------------------------------------------------------------
  527. #pragma segment HeapSeg
  528. size_t MemoryHeap::FreeSlushFund( )
  529. {
  530.     this->Free(fSlushFund);
  531.     fSlushFund = kMMNULL;
  532.     size_t size = fSlushFundSize;
  533.     fSlushFundSize = fSlushFundAllocSizeLimit = 0;
  534.     return size;
  535. }
  536.  
  537. #if MM_DEBUG
  538. //----------------------------------------------------------------------------------------
  539. // MemoryHeap::DeleteHook (MM_DEBUG only)
  540. //----------------------------------------------------------------------------------------
  541. #pragma segment HeapSeg
  542.  
  543. void MemoryHeap::DeleteHook(ODMemoryHook *memoryHook)
  544. {
  545.     this->ValidateMagicNumber();
  546.  
  547.     fMemoryHookList.Remove(memoryHook);
  548. }
  549. #endif
  550.  
  551. #if 0
  552. //----------------------------------------------------------------------------------------
  553. // MemoryHeap::Reset
  554. //----------------------------------------------------------------------------------------
  555. #pragma segment HeapSeg
  556.  
  557. void MemoryHeap::Reset()
  558. {
  559.     this->ValidateMagicNumber();
  560.  
  561. #if MM_DEBUG
  562.     this->CallAboutToResetHooks();
  563. #endif
  564.     
  565.     fBytesAllocated = 0;
  566.     fNumberAllocatedBlocks = 0;
  567.     
  568.     this->DoReset();
  569. }
  570. #endif
  571.  
  572. #if MM_DEBUG
  573. //----------------------------------------------------------------------------------------
  574. // MemoryHeap::SetAutoValidation (MM_DEBUG only)
  575. //----------------------------------------------------------------------------------------
  576. #pragma segment HeapSeg
  577.  
  578. void MemoryHeap::SetAutoValidation(mmboolean autoValidation)
  579. {
  580.     this->ValidateMagicNumber();
  581.  
  582.     fAutoValidation = autoValidation;
  583. }
  584. #endif
  585.  
  586. //----------------------------------------------------------------------------------------
  587. // MemoryHeap::SetDescription
  588. //----------------------------------------------------------------------------------------
  589. #pragma segment HeapSeg
  590.  
  591. void MemoryHeap::SetDescription(const char *description)
  592. {
  593.     this->ValidateMagicNumber();
  594.  
  595.     // ------ Set the description without depending on other code
  596.     
  597.     const char *src = description;
  598.     char *dst = fDescription;
  599.     int i;
  600.     
  601.     for (i = 0; i < kDescriptionLength - 1 && *src; i++)
  602.         *dst++ = *src++;
  603.     fDescription[i] = 0;
  604. }
  605.  
  606. //----------------------------------------------------------------------------------------
  607. // MemoryHeap::SetZapOnAllocate
  608. //----------------------------------------------------------------------------------------
  609. #pragma segment HeapSeg
  610.  
  611. #if MM_DEBUG
  612. void MemoryHeap::SetZapOnAllocate(mmboolean zapOnAllocate)
  613. {
  614.     this->ValidateMagicNumber();
  615.  
  616.     fZapOnAllocate = zapOnAllocate;
  617. }
  618. #endif
  619.  
  620. //----------------------------------------------------------------------------------------
  621. // MemoryHeap::SetZapOnFree
  622. //----------------------------------------------------------------------------------------
  623. #pragma segment HeapSeg
  624.  
  625. #if MM_DEBUG
  626. void MemoryHeap::SetZapOnFree(mmboolean zapOnFree)
  627. {
  628.     this->ValidateMagicNumber();
  629.  
  630.     fZapOnFree = zapOnFree;
  631. }
  632. #endif
  633.  
  634. //----------------------------------------------------------------------------------------
  635. // MemoryHeap::~MemoryHeap
  636. //----------------------------------------------------------------------------------------
  637. #pragma segment HeapSeg
  638.  
  639. MemoryHeap::~MemoryHeap()
  640. {
  641.     this->ValidateMagicNumber();
  642.  
  643.     // ----- Remove from the static list of heaps
  644.     
  645.     MemoryHeap *lastHeap = NULL, *currentHeap = fHeapList;
  646.     
  647.     while (currentHeap != NULL)
  648.     {
  649.         if (this == currentHeap)
  650.         {
  651.             if (lastHeap == NULL)
  652.                 fHeapList = currentHeap->GetNextHeap();
  653.             else
  654.                 lastHeap->fNextHeap = currentHeap->GetNextHeap();
  655.             
  656.             currentHeap = NULL;
  657.         }
  658.         else
  659.         {
  660.             lastHeap = currentHeap;
  661.             currentHeap = currentHeap->GetNextHeap();
  662.         }
  663.     }
  664.  
  665.     // ------ Set the default description without depending on other code
  666.     
  667.     const char *src = kDeadHeapDescription;
  668.     char *dst = fDescription;    
  669.     for (; *src;)
  670.         *dst++ = *src++;
  671.     *dst = 0;
  672.     
  673.     fMagicNumber = 0;
  674. }
  675.  
  676. //----------------------------------------------------------------------------------------
  677. // MemoryHeap::MemoryHeap
  678. //----------------------------------------------------------------------------------------
  679. #pragma segment HeapSeg
  680.  
  681. MemoryHeap::MemoryHeap(mmboolean autoValidation,
  682.                        mmboolean zapOnAllocate,
  683.                        mmboolean zapOnFree,
  684.                        MMHeapLocation memSrc) :
  685. #if MM_DEBUG
  686.     fAutoValidation(autoValidation),
  687.     fZapOnAllocate(zapOnAllocate),
  688.     fZapOnFree(zapOnFree),
  689.     fMemFullMark(0),
  690. #endif
  691.     fBytesAllocated(0),
  692.     fNumberAllocatedBlocks(0),
  693.     fMemSource(memSrc),
  694.     fMagicNumber(kMagicNumber),
  695.     fSlushFund(kMMNULL),
  696.     fSlushFundSize(0),
  697.     fSlushFundAllocSizeLimit(0)
  698. {
  699.     // ------ Set the default description without depending on other code
  700.     
  701.     const char *src = kDefaultDescription;
  702.     char *dst = fDescription;    
  703.     for (; *src;)
  704.         *dst++ = *src++;
  705.     *dst = 0;
  706.     
  707.     // Add to the static list of heaps
  708.     
  709.     fNextHeap = fHeapList;
  710.     fHeapList = this;
  711. }
  712.  
  713. //----------------------------------------------------------------------------------------
  714. // MemoryHeap::operator new
  715. //----------------------------------------------------------------------------------------
  716. #pragma segment HeapSeg
  717.  
  718. void* MemoryHeap::operator new(SIZE_T size, MMHeapLocation src)
  719. {
  720.     return PlatformAllocateBlock(size, src);
  721. }
  722.  
  723. //----------------------------------------------------------------------------------------
  724. // MemoryHeap::operator delete
  725. //----------------------------------------------------------------------------------------
  726. #pragma segment HeapSeg
  727.  
  728. void MemoryHeap::operator delete(void* ptr)
  729. {
  730.         PlatformFreeBlock(ptr);
  731. }
  732.  
  733. //----------------------------------------------------------------------------------------
  734. // MemoryHeap::AllocateRawMemory
  735. //----------------------------------------------------------------------------------------
  736. #pragma segment HeapSeg
  737.  
  738. void *MemoryHeap::AllocateRawMemory(ODBlockSize size)
  739. {
  740.     return PlatformAllocateBlock(size, fMemSource);
  741. }
  742.  
  743. //----------------------------------------------------------------------------------------
  744. // MemoryHeap::DoReallocate
  745. //----------------------------------------------------------------------------------------
  746. #pragma segment HeapSeg
  747.  
  748. void *MemoryHeap::DoReallocate(void *block, ODBlockSize newSize, ODBlockSize &allocatedSize)
  749. {
  750.     ODBlockSize oldRealSize = this->DoBlockSize(block);
  751.     void* newBlock = this->DoAllocate(newSize, allocatedSize);
  752.     
  753.     if (newBlock != NULL)
  754.     {
  755.         ODBlockSize copySize = newSize <= oldRealSize ? newSize : oldRealSize;
  756.         PlatformCopyMemory(block, newBlock, copySize);
  757.  
  758.         #if MM_DEBUG
  759.         if (fZapOnFree)
  760.         {
  761.             char *chrBlk = (char *) block;
  762.             for (ODBlockSize i = 0; i < oldRealSize; i++)
  763.                 *chrBlk++ = 0xDD;
  764.         }
  765.         #endif
  766.  
  767.         this->DoFree(block);
  768.     }
  769.     else
  770.       if (newSize <= oldRealSize)   //if unable to get new fMem, and newSize is <= real size
  771.         return block;               //then return original ptr unchanged
  772.  
  773.     return newBlock;
  774. }
  775.         
  776. //----------------------------------------------------------------------------------------
  777. // MemoryHeap::FreeRawMemory
  778. //----------------------------------------------------------------------------------------
  779. #pragma segment HeapSeg
  780.  
  781. void MemoryHeap::FreeRawMemory(void* ptr)
  782. {
  783.     PlatformFreeBlock(ptr);
  784. }
  785.  
  786. #if MM_DEBUG
  787. //----------------------------------------------------------------------------------------
  788. // MemoryHeap::CompilerCheck (MM_DEBUG only)
  789. //----------------------------------------------------------------------------------------
  790. #pragma segment HeapSeg
  791.  
  792. void MemoryHeap::CompilerCheck()
  793. {
  794. }
  795. #endif
  796.  
  797. #if MM_DEBUG
  798. //----------------------------------------------------------------------------------------
  799. // MemoryHeap::CallAboutToAllocateHooks (MM_DEBUG only)
  800. //----------------------------------------------------------------------------------------
  801. #pragma segment HeapSeg
  802.  
  803. ODBlockSize MemoryHeap::CallAboutToAllocateHooks(ODBlockSize size) const
  804. {
  805.     for (ODMemoryHook *hook = fMemoryHookList.First();
  806.             hook != NULL; hook = fMemoryHookList.After(hook))
  807.         size = hook->AboutToAllocate(size);
  808.         
  809.     return size;
  810. }
  811. #endif
  812.  
  813. #if MM_DEBUG
  814. //----------------------------------------------------------------------------------------
  815. // MemoryHeap::CallGetHeaderSize (MM_DEBUG only)
  816. //----------------------------------------------------------------------------------------
  817. #pragma segment HeapSeg
  818.  
  819. ODBlockSize MemoryHeap::CallGetHeaderSize() const
  820. {
  821.     ODBlockSize size = 0;
  822.     
  823.     for (ODMemoryHook *hook = fMemoryHookList.First();
  824.             hook != NULL; hook = fMemoryHookList.After(hook))
  825.         size += hook->GetHeaderSize();
  826.         
  827.     return size;
  828. }
  829. #endif
  830.  
  831. #if MM_DEBUG
  832. //----------------------------------------------------------------------------------------
  833. // MemoryHeap::CallDidAllocateHooks (MM_DEBUG only)
  834. //----------------------------------------------------------------------------------------
  835. #pragma segment HeapSeg
  836.  
  837. void *MemoryHeap::CallDidAllocateHooks(void* blk, ODBlockSize size)
  838. {
  839.     for (ODMemoryHook *hook = fMemoryHookList.First();
  840.             hook != NULL; hook = fMemoryHookList.After(hook)) {
  841.         blk = hook->DidAllocate(blk, size);
  842.         size -= hook->AboutToAllocate(0);
  843.     }
  844.     return blk;
  845. }
  846. #endif
  847.  
  848. #if MM_DEBUG
  849. //----------------------------------------------------------------------------------------
  850. // MemoryHeap::CallAboutToBlockSizeHooks (MM_DEBUG only)
  851. //----------------------------------------------------------------------------------------
  852. #pragma segment HeapSeg
  853.  
  854. const void *MemoryHeap::CallAboutToBlockSizeHooks(const void* blk) const
  855. {
  856.     for (ODMemoryHook *hook = fMemoryHookList.Last();
  857.             hook != NULL; hook = fMemoryHookList.Before(hook))
  858.         blk = hook->AboutToBlockSize(blk);
  859.         
  860.     return (void*) blk;
  861. }
  862. #endif
  863.  
  864. #if MM_DEBUG
  865. //----------------------------------------------------------------------------------------
  866. // MemoryHeap::CallAboutToFreeHooks (MM_DEBUG only)
  867. //----------------------------------------------------------------------------------------
  868. #pragma segment HeapSeg
  869.  
  870. void *MemoryHeap::CallAboutToFreeHooks(void* blk)
  871. {
  872.     for (ODMemoryHook *hook = fMemoryHookList.Last();
  873.             hook != NULL; hook = fMemoryHookList.Before(hook))
  874.         blk = hook->AboutToFree(blk);
  875.         
  876.     return blk;
  877. }
  878. #endif
  879.  
  880. #if MM_DEBUG
  881. //----------------------------------------------------------------------------------------
  882. // MemoryHeap::CallAboutToReallocHooks (MM_DEBUG only)
  883. //----------------------------------------------------------------------------------------
  884. #pragma segment HeapSeg
  885.  
  886. void MemoryHeap::CallAboutToReallocHooks(void* &blk, ODBlockSize& size)
  887. {
  888.     for (ODMemoryHook *hook = fMemoryHookList.Last();
  889.             hook != NULL; hook = fMemoryHookList.Before(hook))
  890.         hook->AboutToRealloc(blk, size);
  891. }
  892. #endif
  893.  
  894. #if MM_DEBUG
  895. //----------------------------------------------------------------------------------------
  896. // MemoryHeap::CallDidReallocHooks (MM_DEBUG only)
  897. //----------------------------------------------------------------------------------------
  898. #pragma segment HeapSeg
  899.  
  900. void *MemoryHeap::CallDidReallocHooks(void *oldBlk, void *blk, ODBlockSize size)
  901. {
  902.     for (ODMemoryHook *hook = fMemoryHookList.First();
  903.             hook != NULL; hook = fMemoryHookList.After(hook)) {
  904.         blk = hook->DidRealloc(oldBlk, blk, size);
  905.         size -= hook->AboutToAllocate(0);
  906.     }
  907.     return blk;
  908. }
  909. #endif
  910.  
  911. #if MM_DEBUG
  912. //----------------------------------------------------------------------------------------
  913. // MemoryHeap::CallAboutToResetHooks (MM_DEBUG only)
  914. //----------------------------------------------------------------------------------------
  915. #pragma segment HeapSeg
  916.  
  917. void MemoryHeap::CallAboutToResetHooks()
  918. {
  919.     for (ODMemoryHook *hook = fMemoryHookList.First();
  920.             hook != NULL; hook = fMemoryHookList.After(hook))
  921.         hook->AboutToReset();
  922. }
  923. #endif
  924.  
  925. #if MM_DEBUG
  926. //----------------------------------------------------------------------------------------
  927. // MemoryHeap::CallCommentHooks (MM_DEBUG only)
  928. //----------------------------------------------------------------------------------------
  929. #pragma segment HeapSeg
  930.  
  931. void MemoryHeap::CallCommentHooks(const char* comment)
  932. {
  933.     for (ODMemoryHook *hook = fMemoryHookList.First();
  934.             hook != NULL; hook = fMemoryHookList.After(hook))
  935.         hook->Comment(comment);
  936. }
  937. #endif
  938.  
  939. #if MM_DEBUG
  940. //----------------------------------------------------------------------------------------
  941. // MemoryHeap::ValidateAndReport (MM_DEBUG only)
  942. //----------------------------------------------------------------------------------------
  943. #pragma segment HeapSeg
  944.  
  945. void MemoryHeap::ValidateAndReport(void *blk) const
  946. {
  947.     MM_ASSERT(this->IsValidBlock(blk));
  948. }
  949. #endif
  950.  
  951. #if MM_DEBUG
  952. //---------------------------------------------------------------------------------------
  953. // MemoryHeap::SetMemFullMark
  954. //----------------------------------------------------------------------------------------
  955.  
  956. void MemoryHeap::SetMemFullMark()
  957. {
  958.     fMemFullMark = this->BytesFree();
  959. }
  960.  
  961. //----------------------------------------------------------------------------------------
  962. // MemoryHeap::UnsetMemFullMark
  963. //----------------------------------------------------------------------------------------
  964.  
  965. void MemoryHeap::UnsetMemFullMark()
  966. {
  967.     fMemFullMark = 0;
  968. }
  969. #endif
  970.  
  971.